[小ネタ] Pklをビルド時に実行する[Rust]
Introduction
Pkl(ぴっくる)はAppleが開発した、
OSSのconfig file生成用プログラミング言語です。
条件式やループなどの基本構文に加え、クラス・継承・抽象化などの
プログラミング言語機能も使えます。
pklファイルからJSON形式やYAML形式などの各種設定ファイルが出力可能で、
CLIツールや各言語のライブラリやプラグインとして使えます。
現状想定されているユースケースとしては、
下記のものがあります。
Generating Static Configuration(静的構成ファイル生成)
設定ファイルのgenerate機能です。
Pklで記述したコードをJSON、YAML、XML、プロティリスト形式で出力できます。
Application Runtime Configuration(アプリランタイム構成)
Pklをライブラリとして追加し、プログラム内で使用する機能です。
2024年2月時点ではJVM runtime(Java,Kotlin),Swift,Goに対応した
ライブラリが提供されています。
これらは今後追加されるみたいです。
今回はPklをインストールして、
Rustでビルド時にJSONファイルを生成してみます。
Environment
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 13.5.2
- Rust : 1.75.0
Setup
各環境にあわせてPklをインストールします。
自分の環境では下記のようにインストールしました。
% curl -L -o pkl https://github.com/apple/pkl/releases/download/0.25.1/pkl-linux-aarch64 % chmod +x pkl
PklをPATHに追加してコマンドを実行してみます。
% pkl --version Pkl 0.25.1 (macOS 14.1, native)
次にCargoでRustプロジェクトを作成します。
% cargo new pkl-example
あとで確認用に使うのでserdeを追加。
% cd pkl-example % cargo add serde serde_json
プロジェクトのルートにintro.pklを下記内容で作成。
name = "Pkl: Configure your Systems in New Ways" attendants = 100 isInteractive = true amountLearned = 13.37
JSONで標準出力してみる。
% pkl eval -f json ./intro.pkl { "name": "Pkl: Configure your Systems in New Ways", "attendants": 100, "isInteractive": true, "amountLearned": 13.37 }
Cargo.tomlにbuild.rsを指定しましょう。
[package] ・ ・ build = "build.rs"
プロジェクトのルートにbuild.rsを作成します。
雑にpklのパスを設定してJSON出力コマンドを実行するだけです。
// build.rs use std::process::Command; use std::io; use std::env; fn main() -> io::Result<()> { println!("build.rs start"); // 現在のPATHを取得してPATHにpkl追加&環境変数設定 let mut path = env::var_os("PATH").unwrap_or_default(); path.push(":"); path.push("<your pkl path>"); env::set_var("PATH", &path); //pklコマンド実行(intro.json出力) let output = Command::new("pkl") .arg("eval") .arg("-o") .arg("./intro.json") .arg("-f") .arg("json") .arg("./intro.pkl") .output()?; println!("{:?}",output); if !output.status.success() { panic!("Failed to execute pkl command"); } Ok(()) }
src/main.rsでは生成されたjsonファイルにアクセスしてます。
use serde_json::Value; use std::fs; fn main() { let data = fs::read_to_string("intro.json").unwrap(); let v: Value = serde_json::from_str(&data).unwrap(); // JSONデータにアクセスする println!("name: {}", v.get("name").unwrap()); println!("attendants: {}", v.get("attendants").unwrap()); println!("isInteractive: {}", v.get("isInteractive").unwrap()); println!("amountLearned: {}", v.get("amountLearned").unwrap()); }
実行してみます。
jsonが出力されてアクセスできてます。
% cargo build -vv % cargo run ・・・ name: "Pkl: Configure your Systems in New Ways" attendants: 100 isInteractive: true amountLearned: 13.37
Summary
build.rsからシンプルにpklコマンド実行してみました。
Rust用crateはそのうちでてくると思われるので
プログラム内からアクセスするのはもう少し待ちましょう。